#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：tools 
@File ：批量删除文件夹和文件.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2025/1/20 19:00 
"""

# !/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
批量删除文件夹和文件的程序
"""
import os
import shutil
import logging
import queue
import threading
from tkinter import Tk, Label, Entry, Button, messagebox, filedialog
from tkinter.ttk import Progressbar
from typing import Generator

# 配置日志记录
logging.basicConfig(filename="./logs/deletion_errors.log", level=logging.ERROR,
					format="%(asctime)s - %(levelname)s - %(message)s")


def get_all_files_and_folders(root_dir: str) -> Generator[str, None, None]:
	"""
	使用生成器递归获取指定目录下的所有文件和文件夹路径
	:param root_dir: 根目录路径
	:return: 生成器，逐个返回文件或文件夹的路径
	"""
	for root, dirs, files in os.walk(root_dir, topdown=False):
		for name in files:
			yield os.path.join(root, name)  # 返回文件路径
		for name in dirs:
			yield os.path.join(root, name)  # 返回文件夹路径


def delete_files_and_folders(root_dir: str, progress_queue: queue.Queue) -> None:
	"""
	删除指定目录下的所有文件和文件夹
	:param root_dir: 根目录路径
	:param progress_queue: 用于线程间通信的队列
	"""
	total_items = sum(1 for _ in get_all_files_and_folders(root_dir))  # 计算总文件和文件夹数量
	progress_queue.put(("max", total_items))  # 设置进度条最大值
	deleted_count = 0  # 已删除的文件和文件夹数量

	for item in get_all_files_and_folders(root_dir):
		try:
			if os.path.isfile(item) or os.path.islink(item):
				os.unlink(item)  # 删除文件或链接
			elif os.path.isdir(item):
				shutil.rmtree(item)  # 删除文件夹
			deleted_count += 1
			progress_queue.put(("update", deleted_count))  # 更新进度
		except Exception as e:
			logging.error(f"Failed to delete {item}. Reason: {e}")  # 记录错误到日志文件

	progress_queue.put(("complete", "All files and folders have been deleted."))  # 通知完成


def update_progress(progress_queue: queue.Queue, progress_bar: Progressbar) -> None:
	"""
	更新进度条状态
	:param progress_queue: 用于线程间通信的队列
	:param progress_bar: 进度条组件
	"""
	while True:
		message = progress_queue.get()
		if message[0] == "max":
			progress_bar["maximum"] = message[1]  # 设置进度条最大值
		elif message[0] == "update":
			progress_bar["value"] = message[1]  # 更新进度条值
		elif message[0] == "complete":
			messagebox.showinfo("完成", message[1])  # 弹出完成提示
			break


class FileDeletionApp:
	"""
	文件删除程序的GUI界面类
	"""

	def __init__(self, root: Tk) -> None:
		self.root = root
		self.root.title("文件删除程序")
		self.progress_queue = queue.Queue()  # 创建线程间通信队列

		self.setup_ui()  # 初始化界面

	def setup_ui(self) -> None:
		"""
		初始化GUI界面
		"""
		Label(self.root, text="请输入根目录路径:").pack(pady=10)
		self.entry = Entry(self.root, width=50)
		self.entry.pack(pady=10)

		browse_button = Button(self.root, text="浏览", command=self.browse_folder)
		browse_button.pack(pady=10)

		self.progress_bar = Progressbar(self.root, orient="horizontal", length=400, mode="determinate")
		self.progress_bar.pack(pady=20)

		delete_button = Button(self.root, text="删除文件和文件夹", command=self.confirm_delete)
		delete_button.pack(pady=20)

		# 启动进度更新线程
		threading.Thread(target=update_progress, args=(self.progress_queue, self.progress_bar), daemon=True).start()

	def browse_folder(self) -> None:
		"""
		选择文件夹并更新输入框
		"""
		folder_path = filedialog.askdirectory()
		if folder_path:
			self.entry.delete(0, 'end')
			self.entry.insert(0, folder_path)

	def confirm_delete(self) -> None:
		"""
		确认删除操作
		"""
		folder_path = self.entry.get()
		if not folder_path:
			messagebox.showwarning("警告", "请输入目录路径。")
			return
		if not os.path.exists(folder_path):
			messagebox.showerror("错误", "指定的目录不存在。")
			return
		if messagebox.askyesno("确认", f"确定要删除目录 '{folder_path}' 下的所有文件和文件夹吗？"):
			threading.Thread(target=delete_files_and_folders, args=(folder_path, self.progress_queue),
							 daemon=True).start()


if __name__ == "__main__":
	root = Tk()
	app = FileDeletionApp(root)
	root.mainloop()
